const fs = require('fs');
const path = require('path');



function loadWasm(e, wasmPath="") {
    let {
        algorithm,
        challenge,
        salt,
        difficulty,
        signature,
        expire_at
    } = e;

    this.cachedTextEncoder = new TextEncoder()
    this.cachedUint8Memory = null
    this.offset = 0

    this.getCachedUint8Memory = function (){
        if (this.cachedUint8Memory === null || this.cachedUint8Memory.byteLength === 0) {
            this.cachedUint8Memory = new Uint8Array(this.wasmInstance.memory.buffer);
          }
          return this.cachedUint8Memory;
    }
    
    this.encodeString = function (str, allocate, reallocate) {
        // 简单情况：当没有 reallocate 函数时，直接编码整个字符串
        if(!reallocate){
            const encoded = this.cachedTextEncoder.encode(str);
            const ptr = allocate(encoded.length, 1) >>> 0;
            const memory = this.getCachedUint8Memory();
            memory.subarray(ptr, ptr + encoded.length).set(encoded);
            this.offset = encoded.length;
            return ptr;
        }
        // 复杂情况：分两步处理 ASCII 和非 ASCII 字符
        const strLength = str.length;
        let ptr = allocate(strLength, 1) >>> 0;
        const memory = this.getCachedUint8Memory();
        let asciiLength = 0;
        // 首先尝试 ASCII 编码
        for (; asciiLength < strLength; asciiLength++) {
            const charCode = str.charCodeAt(asciiLength);
            if (charCode > 127) break;
            memory[ptr + asciiLength] = charCode;
        }

        // 如果存在非 ASCII 字符，需要重新分配空间并处理
        if (asciiLength !== strLength) {
            if (asciiLength > 0) {
                text = text.slice(asciiLength);
            }
            
            // 为非 ASCII 字符重新分配空间（每个字符最多需要 3 字节）
            ptr = reallocate(ptr, strLength, asciiLength + str.length * 3, 1) >>> 0;
            
            // 使用 encodeInto 处理剩余的非 ASCII 字符
            const result = this.cachedTextEncoder.encodeInto(
                str, 
                this.getCachedUint8Memory().subarray(ptr + asciiLength, ptr + asciiLength + str.length * 3)
            );
            asciiLength += result.written;
            
            // 最终调整内存大小
            ptr = reallocate(ptr, asciiLength + str.length * 3, asciiLength, 1) >>> 0;
        }
  
      this.offset = asciiLength;
      return ptr;
    }

    // 读取 Wasm 文件
    const wasmCode = fs.readFileSync(wasmPath != ""? wasmPath : path.join(__dirname, 'sha3_wasm_bg.7b9ca65ddd.wasm'));
    
    // 定义要传递给 Wasm 的 JavaScript 函数
    const importObject = {
        wbg: {}
    };
    // 编译并实例化 Wasm 模块
    // const { instance } = await WebAssembly.instantiate(wasmCode, importObject);
    const module = new WebAssembly.Module(wasmCode);
    const instance = new WebAssembly.Instance(module, importObject);
    this.wasmInstance = instance.exports;
    //console.log(this.wasmInstance)
    try {
        const prefix = `${salt}_${expire_at}_`;
        // 分配栈空间
        const retptr = this.wasmInstance.__wbindgen_add_to_stack_pointer(-16);
        // 获取编码后的指针和长度
        const ptr0 = this.encodeString(
            challenge,
            this.wasmInstance.__wbindgen_export_0,
            this.wasmInstance.__wbindgen_export_1
        );
        const len0 = this.offset;
        const ptr1 = this.encodeString(
            prefix,
            this.wasmInstance.__wbindgen_export_0,
            this.wasmInstance.__wbindgen_export_1
        );
        const len1 = this.offset;
        //console.log(retptr, ptr0, len0, ptr1, len1, difficulty)
        // 传入正确的长度参数
        this.wasmInstance.wasm_solve(retptr, ptr0, len0, ptr1, len1, difficulty);

        // 获取返回结果
        const dataView = new DataView(this.wasmInstance.memory.buffer);
        const status = dataView.getInt32(retptr + 0, true);
        const value = dataView.getFloat64(retptr + 8, true);
        //console.log(status,value)
        return value
    }finally {
        // 释放栈空间
        this.wasmInstance.__wbindgen_add_to_stack_pointer(16);
    }

}


// function sleep(sm) {
//     const nowTime = new Date();
//     while (Date.now() - nowTime < sm) {
//       continue;
//     }
// }

function main(){
    let data = {
        "algorithm": "DeepSeekHashV1",
        "challenge": "5be4be9f6e2d7189907bf226381f735ee9b6e782ee1f713b501fe07d2dbd0626",
        "salt": "85df87f830baf6dd15a0",
        "signature": "e99b499296e2595ac46fc6bc38485844d2f774ca2fab9b47405547a7493d7c72",
        "difficulty": 144000,
        "expire_at": 1742461733715,
        "expire_after": 300000,
        "target_path": "/api/v0/chat/completion"
    }
    let result = loadWasm(data)
    return result
}

//console.log(main())




